From e803ae0ddc654a3a0f1e4670e07944051642c6e2 Mon Sep 17 00:00:00 2001 From: "sd386@font.cl.cam.ac.uk" Date: Fri, 22 Apr 2005 17:05:34 +0000 Subject: [PATCH] bitkeeper revision 1.1346.1.2 (42692edeXI3qQBmD6woxfDOQaO7VKg) Finished port of the sEDF scheduler to 3.0. sEDF is a new scheduler for Xen, that provides time guarantees using an EDF like algorithm, and also distributes idle cpu time on a weighted fair share policy. Signed off by: Stephan.Diestelhorst@{cl.cam.ac.uk , inf.tu-dresden.de} --- xen/common/sched_sedf.c | 673 ++++++++++++++++++++++------------------ 1 file changed, 365 insertions(+), 308 deletions(-) diff --git a/xen/common/sched_sedf.c b/xen/common/sched_sedf.c index ab1a0697e5..5c2eb80d56 100644 --- a/xen/common/sched_sedf.c +++ b/xen/common/sched_sedf.c @@ -56,10 +56,12 @@ if ((_f)<=SEDFLEVEL) printk(_a ); #define WEIGHT_PERIOD (MILLISECS(100)) #define WEIGHT_SAFETY (MILLISECS(5)) - -struct sedf_dom_info +struct sedf_dom_info { + struct domain *domain; +}; +struct sedf_edom_info { - struct domain *owner; + struct exec_domain *exec_domain; struct list_head list; struct list_head extralist[2]; @@ -79,13 +81,12 @@ struct sedf_dom_info short weight; /*Bookkeeping*/ - s_time_t absdead; - s_time_t sched_start; + s_time_t deadl_abs; + s_time_t sched_start_abs; s_time_t cputime; - s_time_t absblock; - - /*time the domain unblocked, used to determine unblocking intervals*/ - s_time_t absunblock; + /* times the domain un-/blocked */ + s_time_t block_abs; + s_time_t unblock_abs; /*scores for {util, block penalty}-weighted extratime distribution*/ int score[2]; @@ -112,48 +113,47 @@ struct sedf_cpu_info { struct list_head extraq[2]; }; -#define DOM_INFO(d) ((struct sedf_dom_info *)((d)->sched_priv)) +#define EDOM_INFO(d) ((struct sedf_edom_info *)((d)->ed_sched_priv)) #define CPU_INFO(cpu) ((struct sedf_cpu_info *)schedule_data[cpu].sched_priv) -#define LIST(d) (&DOM_INFO(d)->list) -#define EXTRALIST(d,i) (&(DOM_INFO(d)->extralist[i])) +#define LIST(d) (&EDOM_INFO(d)->list) +#define EXTRALIST(d,i) (&(EDOM_INFO(d)->extralist[i])) #define RUNQ(cpu) (&CPU_INFO(cpu)->runnableq) #define WAITQ(cpu) (&CPU_INFO(cpu)->waitq) #define EXTRAQ(cpu,i) (&(CPU_INFO(cpu)->extraq[i])) -#define IDLETASK(cpu) ((struct domain *)schedule_data[cpu].idle) +#define IDLETASK(cpu) ((struct exec_domain *)schedule_data[cpu].idle) -#define PERIOD_BEGIN(inf) ((inf)->absdead - (inf)->period) +#define PERIOD_BEGIN(inf) ((inf)->deadl_abs - (inf)->period) #define MIN(x,y) (((x)<(y))?(x):(y)) #define DIV_UP(x,y) (((x) + (y) - 1) / y) -static xmem_cache_t *dom_info_cache; - static void sedf_dump_cpu_state(int i); -static inline int extraq_on(struct domain *d, int i) { +static inline int extraq_on(struct exec_domain *d, int i) { return ((EXTRALIST(d,i)->next != NULL) && (EXTRALIST(d,i)->next != EXTRALIST(d,i))); } -static inline void extraq_add_head(struct domain *d, int i) +static inline void extraq_add_head(struct exec_domain *d, int i) { list_add(EXTRALIST(d,i), EXTRAQ(d->processor,i)); } -static inline void extraq_add_tail(struct domain *d, int i) +static inline void extraq_add_tail(struct exec_domain *d, int i) { list_add_tail(EXTRALIST(d,i), EXTRAQ(d->processor,i)); } -static inline void extraq_del(struct domain *d, int i) +static inline void extraq_del(struct exec_domain *d, int i) { struct list_head *list = EXTRALIST(d,i); /*if (!extraq_on(d,i)) { - PRINT(0,"extraq_del: domain %i is NOT on L%i extraq "\ - "HALTING\n",d->id,i); + PRINT(0,"extraq_del: domain %i.%i is NOT on L%i extraq "\ + "HALTING\n",d->domain->id, d->eid,i); sedf_dump_cpu_state(0);(*((int*)0))++; }*/ - PRINT(3, "Removing domain %i from L%i extraq\n", d->id,i); + PRINT(3, "Removing domain %i.%i from L%i extraq\n", d->domain->id, + d->eid, i); list_del(list); list->next = NULL; } @@ -164,28 +164,29 @@ static inline void extraq_del(struct domain *d, int i) each entry, in order to avoid overflow. The algorithm works by simply charging each domain that recieved extratime with an inverse of its weight. */ -static inline void extraq_add_sort_update(struct domain *d, int i, int sub) { - struct list_head *cur; - struct sedf_dom_info *curinf; +static inline void extraq_add_sort_update(struct exec_domain *d, int i, int sub) { + struct list_head *cur; + struct sedf_edom_info *curinf; /*if (extraq_on(d,i)) { - PRINT(0,"extraq_add_sort_update: domain %i is already on "\ - "L%i extraq! HALTING\n",d->id,i); + PRINT(0,"extraq_add_sort_update: domain %i.%i is already on "\ + "L%i extraq! HALTING\n",d->domain->id, d->eid, i); sedf_dump_cpu_state(0);(*((int*)0))++; }*/ - PRINT(3, "Adding domain %i (score= %i, short_pen= %lli) to L%i "\ - "extraq\n", d->id, DOM_INFO(d)->score[i], - DOM_INFO(d)->short_block_lost_tot, i); + PRINT(3, "Adding domain %i.%i (score= %i, short_pen= %lli) to L%i "\ + "extraq\n", d->domain->id, d->eid, EDOM_INFO(d)->score[i], + EDOM_INFO(d)->short_block_lost_tot, i); /*iterate through all elements to find our "hole" and on our way update all the other scores*/ list_for_each(cur,EXTRAQ(d->processor,i)){ - curinf = list_entry(cur,struct sedf_dom_info,extralist[i]); + curinf = list_entry(cur,struct sedf_edom_info,extralist[i]); curinf->score[i] -= sub; - if (DOM_INFO(d)->score[i] < curinf->score[i]) + if (EDOM_INFO(d)->score[i] < curinf->score[i]) break; else - PRINT(4,"\tbehind domain %i (score= %i)\n", - curinf->owner->id, curinf->score[i]); + PRINT(4,"\tbehind domain %i.%i (score= %i)\n", + curinf->exec_domain->domain->id, + curinf->exec_domain->eid, curinf->score[i]); } /*cur now contains the element, before which we'll enqueue*/ PRINT(3, "\tlist_add to %x\n", cur->prev); @@ -195,24 +196,27 @@ static inline void extraq_add_sort_update(struct domain *d, int i, int sub) { if ((cur != EXTRAQ(d->processor,i)) && sub) for (cur = cur->next; cur != EXTRAQ(d->processor,i); cur = cur-> next) { - curinf = list_entry(cur,struct sedf_dom_info, + curinf = list_entry(cur,struct sedf_edom_info, extralist[i]); curinf->score[i] -= sub; - PRINT(4, "\tupdating domain %i (score= %llu)\n", - curinf->owner->id, curinf->score[i]); + PRINT(4, "\tupdating domain %i.%i (score= %llu)\n", + curinf->exec_domain->domain->id, + curinf->exec_domain->eid, curinf->score[i]); } } -static inline void extraq_check(struct domain *d) { +static inline void extraq_check(struct exec_domain *d) { if (extraq_on(d, EXTRA_UTIL_Q)) { - PRINT(2,"Dom %i is on extraQ\n",d->id); - if (!(DOM_INFO(d)->extra & EXTRA_AWARE) && - !extra_runs(DOM_INFO(d))) { + PRINT(2,"Dom %i is on extraQ\n",d->domain->id, d->eid); + if (!(EDOM_INFO(d)->extra & EXTRA_AWARE) && + !extra_runs(EDOM_INFO(d))) { extraq_del(d, EXTRA_UTIL_Q); - PRINT(2,"Removed dom %i from L1 extraQ\n",d->id); + PRINT(2,"Removed dom %i.%i from L1 extraQ\n", + d->domain->id, d->eid); } } else { - PRINT(2,"Dom %i is NOT on L1 extraQ\n",d->id); - if ((DOM_INFO(d)->extra & EXTRA_AWARE) && domain_runnable(d)) + PRINT(2,"Dom %i.%i is NOT on L1 extraQ\n",d->domain->id, + d->eid); + if ((EDOM_INFO(d)->extra & EXTRA_AWARE) && domain_runnable(d)) { #if (EXTRA == EXTRA_ROUNDR) /*Favour domains which got short unblocked*/ @@ -223,15 +227,16 @@ static inline void extraq_check(struct domain *d) { #elif ; #endif - PRINT(2,"Added dom %i to L1 extraQ\n",d->id); + PRINT(2,"Added dom %i.%i to L1 extraQ\n",d->domain->id, + d->eid); } } } -static inline void __del_from_queue(struct domain *d) +static inline void __del_from_queue(struct exec_domain *d) { struct list_head *list = LIST(d); - PRINT(3,"Removing domain %i (bop= %llu) from runq/waitq\n", d->id, - PERIOD_BEGIN(DOM_INFO(d))); + PRINT(3,"Removing domain %i.%i (bop= %llu) from runq/waitq\n", d->domain->id, + d->eid, PERIOD_BEGIN(EDOM_INFO(d))); list_del(list); list->next = NULL; } @@ -240,26 +245,26 @@ static inline void __del_from_queue(struct domain *d) next period; this list is therefore sortet by this time, which is simply absol. deadline - period */ -static inline void __add_to_waitqueue_sort(struct domain *d) { +static inline void __add_to_waitqueue_sort(struct exec_domain *d) { struct list_head *cur; - struct sedf_dom_info *curinf; + struct sedf_edom_info *curinf; - PRINT(3,"Adding domain %i (bop= %llu) to waitq\n", d->id, - PERIOD_BEGIN(DOM_INFO(d))); + PRINT(3,"Adding domain %i.%i (bop= %llu) to waitq\n", d->domain->id, + d->eid, PERIOD_BEGIN(EDOM_INFO(d))); /*iterate through all elements to find our "hole"*/ - list_for_each(cur,WAITQ(d->processor)){ - curinf = list_entry(cur,struct sedf_dom_info,list); - if (PERIOD_BEGIN(DOM_INFO(d)) < PERIOD_BEGIN(curinf)) + list_for_each(cur, WAITQ(d->processor)){ + curinf = list_entry(cur,struct sedf_edom_info,list); + if (PERIOD_BEGIN(EDOM_INFO(d)) < PERIOD_BEGIN(curinf)) break; else - PRINT(4,"\tbehind domain %i (bop= %llu)\n", - curinf->owner->id, PERIOD_BEGIN(curinf)); + PRINT(4,"\tbehind domain %i.%i (bop= %llu)\n", + curinf->exec_domain->domain->id, + curinf->exec_domain->eid, PERIOD_BEGIN(curinf)); } /*cur now contains the element, before which we'll enqueue*/ PRINT(3,"\tlist_add to %x\n",cur->prev); list_add(LIST(d),cur->prev); - } /* adds a domain to the queue of processes which have started their current @@ -267,40 +272,40 @@ static inline void __add_to_waitqueue_sort(struct domain *d) { on this list is running on the processor, if the list is empty the idle task will run. As we are implementing EDF, this list is sorted by deadlines. */ -static inline void __add_to_runqueue_sort(struct domain *d) { +static inline void __add_to_runqueue_sort(struct exec_domain *d) { struct list_head *cur; - struct sedf_dom_info *curinf; + struct sedf_edom_info *curinf; - PRINT(3,"Adding domain %i (deadl= %llu) to runq\n", d->id, - DOM_INFO(d)->absdead); + PRINT(3,"Adding domain %i.%i (deadl= %llu) to runq\n", d->domain->id, + d->eid, EDOM_INFO(d)->deadl_abs); /*iterate through all elements to find our "hole"*/ list_for_each(cur, RUNQ(d->processor)) { - curinf = list_entry(cur, struct sedf_dom_info, list); - if (DOM_INFO(d)->absdead < curinf->absdead) + curinf = list_entry(cur, struct sedf_edom_info, list); + if (EDOM_INFO(d)->deadl_abs < curinf->deadl_abs) break; else - PRINT(4,"\tbehind domain %i (deadl= %llu)\n", - curinf->owner->id, curinf->absdead); + PRINT(4,"\tbehind domain %i.%i (deadl= %llu)\n", + curinf->exec_domain->domain->id, + curinf->exec_domain->eid, curinf->deadl_abs); } /*cur now contains the element, before which we'll enqueue*/ PRINT(3,"\tlist_add to %x\n",cur->prev); list_add(LIST(d),cur->prev); - } -static inline int __task_on_queue(struct domain *d) { +static inline int __task_on_queue(struct exec_domain *d) { return (((LIST(d))->next != NULL) && (LIST(d)->next != LIST(d))); } -/* Initialises the queues and creates the domain info cache */ +/* Initialises the queues */ static int sedf_init_scheduler() { int i; PRINT(2,"sedf_init_scheduler was called\n"); for ( i = 0; i < NR_CPUS; i++ ) { schedule_data[i].sched_priv = - xmalloc(sizeof(struct sedf_cpu_info)); + xmalloc(struct sedf_cpu_info); if ( schedule_data[i].sched_priv == NULL ) return -1; INIT_LIST_HEAD(WAITQ(i)); @@ -308,46 +313,56 @@ static int sedf_init_scheduler() { INIT_LIST_HEAD(EXTRAQ(i,EXTRA_PEN_Q)); INIT_LIST_HEAD(EXTRAQ(i,EXTRA_UTIL_Q)); } - dom_info_cache = xmem_cache_create("SEDF dom info", +//TODO: Remove this stuff if things work! + /*dom_info_cache = xmem_cache_create("SEDF dom info", sizeof(struct sedf_dom_info), 0, 0, 0, NULL); if ( dom_info_cache == NULL ) { printk("Could not allocate SLAB cache.\n"); return -1; - } + }*/ return 0; } /* Allocates memory for per domain private scheduling data*/ -static int sedf_alloc_task(struct domain *d) { - PRINT(2,"sedf_alloc_task was called, domain-id %i\n",d->id); - if ( (d->sched_priv = xmem_cache_alloc(dom_info_cache)) == NULL ) +static int sedf_alloc_task(struct exec_domain *d) { + PRINT(2,"sedf_alloc_task was called, domain-id %i.%i\n",d->domain->id, + d->eid); + if (d->domain->sched_priv == NULL) { + if ((d->domain->sched_priv = + xmalloc(struct sedf_dom_info)) == NULL ) return -1; - memset(d->sched_priv, 0, sizeof(struct sedf_dom_info)); + memset(d->domain->sched_priv, 0, sizeof(struct sedf_dom_info)); + } + if ((d->ed_sched_priv = xmalloc(struct sedf_edom_info)) == NULL ) + return -1; + memset(d->ed_sched_priv, 0, sizeof(struct sedf_edom_info)); return 0; } /* Setup the sedf_dom_info */ -static void sedf_add_task(struct domain *d) +static void sedf_add_task(struct exec_domain *d) { - struct sedf_dom_info *inf=DOM_INFO(d); - inf->owner = d; + struct sedf_edom_info *inf=EDOM_INFO(d); + inf->exec_domain = d; - PRINT(2,"sedf_add_task was called, domain-id %i\n",d->id); - if (d->id==0) { + PRINT(2,"sedf_add_task was called, domain-id %i.%i\n",d->domain->id, + d->eid); + + if (d->domain->id==0) { /*set dom0 to something useful to boot the machine*/ inf->period = MILLISECS(20); inf->slice = MILLISECS(15); inf->latency = 0; - inf->absdead = 0; + inf->deadl_abs = 0; inf->extra = EXTRA_NONE;/*EXTRA_AWARE; */ } else { /*other domains run in best effort mode*/ inf->period = MILLISECS(20); inf->slice = 0; - inf->absdead = 0; + inf->deadl_abs = 0; inf->latency = 0; inf->extra = EXTRA_AWARE; } @@ -360,31 +375,39 @@ static void sedf_add_task(struct domain *d) /* Frees memory used by domain info */ static void sedf_free_task(struct domain *d) { + int i; PRINT(2,"sedf_free_task was called, domain-id %i\n",d->id); ASSERT(d->sched_priv != NULL); - xmem_cache_free(dom_info_cache, d->sched_priv); + xfree(d->sched_priv); + + for (i = 0; i < MAX_VIRT_CPUS; i++) + if ( d->exec_domain[i] ) { + ASSERT(d->exec_domain[i]->ed_sched_priv != NULL); + xfree(d->exec_domain[i]->ed_sched_priv); + } } /* Initialises idle task */ -static int sedf_init_idle_task(struct domain *d) { - PRINT(2,"sedf_init_idle_task was called, domain-id %i\n",d->id); +static int sedf_init_idle_task(struct exec_domain *d) { + PRINT(2,"sedf_init_idle_task was called, domain-id %i.%i\n", + d->domain->id, d->eid); if ( sedf_alloc_task(d) < 0 ) return -1; sedf_add_task(d); - DOM_INFO(d)->absdead = 0; - set_bit(DF_RUNNING, &d->flags); + EDOM_INFO(d)->deadl_abs = 0; + set_bit(EDF_RUNNING, &d->ed_flags); /*the idle task doesn't have to turn up on any list...*/ return 0; } /* handles the rescheduling, bookkeeping of domains running in their realtime-time :)*/ -static inline void desched_edf_dom (s_time_t now, struct domain* d) { - struct sedf_dom_info* inf = DOM_INFO(d); +static inline void desched_edf_dom (s_time_t now, struct exec_domain* d) { + struct sedf_edom_info* inf = EDOM_INFO(d); /*current domain is running in real time mode*/ /*update the domains cputime*/ - inf->cputime += now - inf->sched_start; + inf->cputime += now - inf->sched_start_abs; /*scheduling decisions, which don't remove the running domain from the runq*/ @@ -392,9 +415,9 @@ static inline void desched_edf_dom (s_time_t now, struct domain* d) { return; __del_from_queue(d); - /*if (__task_on_queue(current)) { - PRINT(0,"domain %i was removed but still on run/waitq => "\ - "HALT\n",current->id); + /*if (__task_on_queue(d)) { + PRINT(0,"domain %i.%i was removed but still on run/waitq => "\ + "HALT\n",d->domain->id, d->eid); sedf_dump_cpu_state(0);(*((int*)0))++; }*/ @@ -406,7 +429,7 @@ static inline void desched_edf_dom (s_time_t now, struct domain* d) { if (inf->period < inf->period_orig) { /*this domain runs in latency scaling or burst mode*/ #if (UNBLOCK == UNBLOCK_BURST) - if (now - inf->absunblock >= 2 * inf->period) + if (now - inf->unblock_abs >= 2 * inf->period) #endif { inf->period *= 2; inf->slice *= 2; @@ -419,43 +442,44 @@ static inline void desched_edf_dom (s_time_t now, struct domain* d) { } } /*set next deadline*/ - inf->absdead += inf->period; + inf->deadl_abs += inf->period; } - /*if (inf->absdeadid, now, - inf->absdead);*/ + /*if (inf->deadl_abs < now) + printk("Domain %i.%i exceeded it't deadline!!!! "\ + "(now: %llu ddl: %llu)\n", d->domain->id, d->eid, now, + inf->deadl_abs);*/ /*add a runnable domain to the waitqueue*/ if (domain_runnable(d)) __add_to_waitqueue_sort(d); else { - /*we have a blocked realtime task*/ - inf->absblock = now; + /*we have a blocked realtime task -> remove it from exqs too*/ + inf->block_abs = now; #if (EXTRA > EXTRA_OFF) #if (EXTRA == EXTRA_BLOCK_WEIGHT) - if (extraq_on(d,EXTRA_PEN_Q)) extraq_del(d,EXTRA_PEN_Q); + if (extraq_on(d, EXTRA_PEN_Q)) extraq_del(d, EXTRA_PEN_Q); #endif - if (extraq_on(d,EXTRA_UTIL_Q)) extraq_del(d,EXTRA_UTIL_Q); + if (extraq_on(d, EXTRA_UTIL_Q)) extraq_del(d, EXTRA_UTIL_Q); #endif } } /* Update all elements on the queues */ -static inline void update_queues( -s_time_t now, struct list_head* runq, struct list_head* waitq) { +static inline void update_queues(s_time_t now, struct list_head* runq, +struct list_head* waitq) { struct list_head *cur,*tmp; - struct sedf_dom_info *curinf; + struct sedf_edom_info *curinf; PRINT(3,"Updating waitq..\n"); /*check for the first elements of the waitqueue, whether their next period has already started*/ list_for_each_safe(cur, tmp, waitq) { - curinf = list_entry(cur, struct sedf_dom_info, list); - PRINT(4,"\tLooking @ dom %i\n", curinf->owner->id); + curinf = list_entry(cur, struct sedf_edom_info, list); + PRINT(4,"\tLooking @ dom %i.%i\n", + curinf->exec_domain->domain->id, curinf->exec_domain->eid); if (PERIOD_BEGIN(curinf) <= now) { - __del_from_queue(curinf->owner); - __add_to_runqueue_sort(curinf->owner); + __del_from_queue(curinf->exec_domain); + __add_to_runqueue_sort(curinf->exec_domain); } else break; @@ -465,48 +489,52 @@ s_time_t now, struct list_head* runq, struct list_head* waitq) { /*process the runq, find domains that are on the runqueue which shouldn't be there*/ list_for_each_safe(cur, tmp, runq) { - curinf = list_entry(cur,struct sedf_dom_info,list); - PRINT(4,"\tLooking @ dom %i\n", curinf->owner->id); + curinf = list_entry(cur,struct sedf_edom_info,list); + PRINT(4,"\tLooking @ dom %i.%i\n", + curinf->exec_domain->domain->id, curinf->exec_domain->eid); if (unlikely(curinf->slice == 0)) { /*ignore domains with empty slice*/ - PRINT(4,"\tUpdating zero-slice domain %i\n", - curinf->owner->id); - __del_from_queue(curinf->owner); + PRINT(4,"\tUpdating zero-slice domain %i.%i\n", + curinf->exec_domain->domain->id, + curinf->exec_domain->eid); + __del_from_queue(curinf->exec_domain); /*move them to their next period*/ - curinf->absdead += curinf->period; + curinf->deadl_abs += curinf->period; /*and put them back into the queue*/ - __add_to_waitqueue_sort(curinf->owner); + __add_to_waitqueue_sort(curinf->exec_domain); } else { - if (unlikely((curinf->absdead < now) || + if (unlikely((curinf->deadl_abs < now) || (curinf->cputime > curinf->slice))) { /*we missed the deadline or the slice was already finished... might hapen because of dom_adj.*/ - PRINT(4,"\tDomain %i exceeded it's deadline/"\ + PRINT(4,"\tDomain %i.%i exceeded it's deadline/"\ "slice (%llu / %llu) now: %llu "\ - "cputime: %llu\n", curinf->owner->id, - curinf->absdead, curinf->slice, now, + "cputime: %llu\n", + curinf->exec_domain->domain->id, + curinf->exec_domain->eid, + curinf->deadl_abs, curinf->slice, now, curinf->cputime); - __del_from_queue(curinf->owner); + __del_from_queue(curinf->exec_domain); /*common case: we miss one period!*/ - curinf->absdead += curinf->period; + curinf->deadl_abs += curinf->period; /*if we are still behind: modulo arithmetic, force deadline to be in future and aligned to period borders!*/ - if (unlikely(curinf->absdead < now)) - curinf->absdead += - DIV_UP(now - curinf->absdead, + if (unlikely(curinf->deadl_abs < now)) + curinf->deadl_abs += + DIV_UP(now - curinf->deadl_abs, curinf->period) * curinf->period; - + ASSERT(curinf->deadl_abs > now); /*give a fresh slice*/ curinf->cputime = 0; - if (PERIOD_BEGIN(curinf) < now) - __add_to_waitqueue_sort(curinf->owner); + if (PERIOD_BEGIN(curinf) > now) + __add_to_waitqueue_sort(curinf->exec_domain); else - __add_to_runqueue_sort(curinf->owner); + __add_to_runqueue_sort(curinf->exec_domain); } else break; @@ -522,8 +550,8 @@ s_time_t now, struct list_head* runq, struct list_head* waitq) { weighted ext.: insert in sorted list by score if the domain is blocked / has regained its short-block-loss time it is not put on any queue */ -static inline void desched_extra_dom(s_time_t now, struct domain* d) { - struct sedf_dom_info *inf = DOM_INFO(d); +static inline void desched_extra_dom(s_time_t now, struct exec_domain* d) { + struct sedf_edom_info *inf = EDOM_INFO(d); int i = extra_get_cur_q(inf); #if (EXTRA == EXTRA_SLICE_WEIGHT || EXTRA == EXTRA_BLOCK_WEIGHT) @@ -535,7 +563,7 @@ static inline void desched_extra_dom(s_time_t now, struct domain* d) { /*fresh slice for the next run*/ inf->cputime = 0; /*accumulate total extratime*/ - inf->extra_time_tot += now - inf->sched_start; + inf->extra_time_tot += now - inf->sched_start_abs; /*remove extradomain from head of the queue*/ extraq_del(d, i); @@ -551,11 +579,13 @@ static inline void desched_extra_dom(s_time_t now, struct domain* d) { /*domain was running in L0 extraq*/ /*reduce block lost, probably more sophistication here!*/ /*inf->short_block_lost_tot -= EXTRA_QUANTUM;*/ - inf->short_block_lost_tot -= now - inf->sched_start; - PRINT(3,"Domain %i: Short_block_lost: %lli\n", - inf->owner->id, inf->short_block_lost_tot); + inf->short_block_lost_tot -= now - inf->sched_start_abs; + PRINT(3,"Domain %i.%i: Short_block_loss: %lli\n", + inf->exec_domain->domain->id, inf->exec_domain->eid, + inf->short_block_lost_tot); if (inf->short_block_lost_tot <= 0) { - PRINT(4,"Domain %i compensated short block loss!\n"); + PRINT(4,"Domain %i.%i compensated short block loss!\n", + inf->exec_domain->domain->id, inf->exec_domain->eid); /*we have (over-)compensated our block penalty*/ inf->short_block_lost_tot = 0; /*we don't want a place on the penalty queue anymore!*/ @@ -574,6 +604,7 @@ static inline void desched_extra_dom(s_time_t now, struct domain* d) { { /*domain was running in L1 extraq => score is inverse of utilization and is used somewhat incremental!*/ +//TODO: Check for weights => use them for calculating the score! if (inf->slice) /*NB: use fixed point arithmetic with 10 bits*/ inf->score[EXTRA_UTIL_Q] = (inf->period << 10) / @@ -586,47 +617,47 @@ static inline void desched_extra_dom(s_time_t now, struct domain* d) { /*add according to score: weighted round robin*/ extraq_add_sort_update(d, i, oldscore); else { - inf->absblock = now; + inf->block_abs = now; /*if (!__task_on_queue(d)) - printf("Oops... We attempt to remove d %i from the "\ - "waitq, but it is not on :(\n",d->id);*/ + printf("Oops... We attempt to remove d %i.%i from the "\ + "waitq, but it is not on :(\n", d->domain->id, + d->eid);*/ /*remove this blocked domain from the waitq!*/ __del_from_queue(d); /*make sure that we remove a blocked domain from the other extraq aswell (this caused hours of debugging!)*/ #if (EXTRA == EXTRA_BLOCK_WEIGHT) if (i == EXTRA_PEN_Q) { - if (extraq_on(d,EXTRA_UTIL_Q)) - extraq_del(d,EXTRA_UTIL_Q); + if (extraq_on(d, EXTRA_UTIL_Q)) + extraq_del(d, EXTRA_UTIL_Q); } else { - if (extraq_on(d,EXTRA_PEN_Q)) - extraq_del(d,EXTRA_PEN_Q); + if (extraq_on(d, EXTRA_PEN_Q)) + extraq_del(d, EXTRA_PEN_Q); } #endif } #endif /*if (!domain_runnable(d)) { - if (extraq_on(d,EXTRA_UTIL_Q)) { - PRINT(0,"domain %i is blocked but still on L1 "\ - "xq=> HALT\n",d->id); + if (extraq_on(d, EXTRA_UTIL_Q)) { + PRINT(0,"domain %i.%i is blocked but still on L1 "\ + "xq=> HALT\n",d->domain->id, d->eid); sedf_dump_cpu_state(0);(*((int*)0))++; } if (__task_on_queue(d)) { - PRINT(0,"domain %i is blocked but still on run/waitq"\ - "=> HALT\n",d->id); + PRINT(0,"domain %i.%i is blocked but still on run/waitq"\ + "=> HALT\n",d->domain->id, d->eid); sedf_dump_cpu_state(0);(*((int*)0))++; } }*/ } #endif - -static inline task_slice_t sedf_do_extra_schedule -(s_time_t now, s_time_t end_xt, struct list_head *extraq[], int cpu) { - task_slice_t ret; - struct sedf_dom_info *runinf; +static inline struct task_slice sedf_do_extra_schedule (s_time_t now, s_time_t end_xt, struct list_head *extraq[], int cpu) { + struct task_slice ret; + struct sedf_edom_info *runinf; + /* Enough time left to use for extratime? */ if (end_xt - now < EXTRA_QUANTUM) goto return_idle; #if (EXTRA == EXTRA_BLOCK_WEIGHT) @@ -634,9 +665,9 @@ static inline task_slice_t sedf_do_extra_schedule /*we still have elements on the level 0 extraq => let those run first!*/ runinf = list_entry(extraq[EXTRA_PEN_Q]->next, - struct sedf_dom_info, extralist[EXTRA_PEN_Q]); + struct sedf_edom_info, extralist[EXTRA_PEN_Q]); runinf->extra |= EXTRA_RUN_PEN; - ret.task = runinf->owner; + ret.task = runinf->exec_domain; ret.time = EXTRA_QUANTUM; #ifdef SEDF_STATS runinf->pen_extra_slices++; @@ -646,9 +677,9 @@ static inline task_slice_t sedf_do_extra_schedule if (!list_empty(extraq[EXTRA_UTIL_Q])) { /*use elements from the normal extraqueue*/ runinf = list_entry(extraq[EXTRA_UTIL_Q]->next, - struct sedf_dom_info,extralist[EXTRA_UTIL_Q]); + struct sedf_edom_info, extralist[EXTRA_UTIL_Q]); runinf->extra |= EXTRA_RUN_UTIL; - ret.task = runinf->owner; + ret.task = runinf->exec_domain; ret.time = EXTRA_QUANTUM; } else @@ -666,20 +697,20 @@ return_idle: -timeslice for the current period used up -domain on waitqueue has started it's period -and various others ;) in general: determine which domain to run next*/ -static task_slice_t sedf_do_schedule(s_time_t now) +static struct task_slice sedf_do_schedule(s_time_t now) { int cpu = current->processor; struct list_head *runq = RUNQ(cpu); struct list_head *waitq = WAITQ(cpu); #if (EXTRA > EXTRA_OFF) - struct sedf_dom_info *inf = DOM_INFO(current); - struct list_head *extraq[] = {EXTRAQ(cpu,EXTRA_PEN_Q), + struct sedf_edom_info *inf = EDOM_INFO(current); + struct list_head *extraq[] = {EXTRAQ(cpu, EXTRA_PEN_Q), EXTRAQ(cpu, EXTRA_UTIL_Q)}; #endif - task_slice_t ret; + struct task_slice ret; /*int i = 0;*/ /*idle tasks don't need any of the following stuf*/ - if (is_idle_task(current)) + if (is_idle_task(current->domain)) goto check_waitq; #if (EXTRA > EXTRA_OFF) @@ -696,28 +727,31 @@ static task_slice_t sedf_do_schedule(s_time_t now) } /*if (!domain_runnable(current)) { if (extraq_on(current,EXTRA_UTIL_Q)) { - PRINT(0,"domain %i is blocked but still on L1 xq"\ - " branch %i=> HALT\n", current->id, i); + PRINT(0,"domain %i.%i is blocked but still on L1 xq"\ + " branch %i=> HALT\n", current->domain->id, + current->eid, i); sedf_dump_cpu_state(0);(*((int*)0))++; } if (__task_on_queue(current)) { - PRINT(0,"domain %i is blocked but still on run/waitq"\ - " branch %i=> HALT\n",current->id,i); + PRINT(0,"domain %i.%i is blocked but still on run/waitq"\ + " branch %i=> HALT\n",current->domain->id, + d->eid,i); sedf_dump_cpu_state(0);(*((int*)0))++; } }*/ check_waitq: update_queues(now, runq, waitq); - /*now simply pick the first domain from the runqueue*/ - struct sedf_dom_info *runinf, *waitinf; + /*now simply pick the first domain from the runqueue, which has the + earliest deadline, because the list is sorted*/ + struct sedf_edom_info *runinf, *waitinf; if (!list_empty(runq)) { - runinf = list_entry(runq->next,struct sedf_dom_info,list); - ret.task = runinf->owner; + runinf = list_entry(runq->next,struct sedf_edom_info,list); + ret.task = runinf->exec_domain; if (!list_empty(waitq)) { waitinf = list_entry(waitq->next, - struct sedf_dom_info,list); + struct sedf_edom_info,list); /*rerun scheduler, when scheduled domain reaches it's end of slice or the first domain from the waitqueue gets ready*/ @@ -727,11 +761,12 @@ check_waitq: else { ret.time = runinf->slice - runinf->cputime; } + ASSERT(ret.time > now); goto sched_done; } if (!list_empty(waitq)) { - waitinf = list_entry(waitq->next,struct sedf_dom_info,list); + waitinf = list_entry(waitq->next,struct sedf_edom_info, list); /*we could not find any suitable domain => look for domains that are aware of extratime*/ #if (EXTRA > EXTRA_OFF) @@ -741,6 +776,7 @@ check_waitq: ret.task = IDLETASK(cpu); ret.time = PERIOD_BEGIN(waitinf) - now; #endif + ASSERT(ret.time > now); } else { /*this could probably never happen, but one never knows...*/ @@ -758,13 +794,13 @@ sched_done: ret.time); ret.time = EXTRA_QUANTUM; } - DOM_INFO(ret.task)->sched_start=now; + EDOM_INFO(ret.task)->sched_start_abs = now; return ret; } -static void sedf_sleep(struct domain *d) { - PRINT(2,"sedf_sleep was called, domain-id %i\n",d->id); - if ( test_bit(DF_RUNNING, &d->flags) ) { +static void sedf_sleep(struct exec_domain *d) { + PRINT(2,"sedf_sleep was called, domain-id %i.%i\n",d->domain->id, d->eid); + if ( test_bit(EDF_RUNNING, &d->ed_flags) ) { #ifdef ADV_SCHED_HISTO adv_sched_hist_start(d->processor); #endif @@ -856,15 +892,15 @@ static void sedf_sleep(struct domain *d) { * opposed to approaches 1,2a,2b */ static inline void unblock_short_vcons -(struct sedf_dom_info* inf, s_time_t now) { - inf->absdead += inf->period; +(struct sedf_edom_info* inf, s_time_t now) { + inf->deadl_abs += inf->period; inf->cputime = 0; } -static inline void unblock_short_cons(struct sedf_dom_info* inf, s_time_t now) +static inline void unblock_short_cons(struct sedf_edom_info* inf, s_time_t now) { /*treat blocked time as consumed by the domain*/ - inf->cputime += now - inf->absblock; + inf->cputime += now - inf->block_abs; if (inf->cputime + EXTRA_QUANTUM > inf->slice) { /*we don't have a reasonable amount of time in our slice left :( => start in next period!*/ @@ -875,7 +911,7 @@ static inline void unblock_short_cons(struct sedf_dom_info* inf, s_time_t now) inf->short_cont++; #endif } -static inline void unblock_short_extra_support (struct sedf_dom_info* inf, +static inline void unblock_short_extra_support (struct sedf_edom_info* inf, s_time_t now) { /*this unblocking scheme tries to support the domain, by assigning it a priority in extratime distribution according to the loss of time @@ -883,10 +919,12 @@ static inline void unblock_short_extra_support (struct sedf_dom_info* inf, s_time_t pen; /*no more realtime execution in this period!*/ - inf->absdead += inf->period; - if (likely(inf->absblock)) { + inf->deadl_abs += inf->period; + if (likely(inf->block_abs)) { //treat blocked time as consumed by the domain*/ - /*inf->cputime += now - inf->absblock;*/ + /*inf->cputime += now - inf->block_abs;*/ + /*penalty is time the domain would have + had if it continued to run */ pen = (inf->slice - inf->cputime); if (pen < 0) pen = 0; /*accumulate all penalties over the periods*/ @@ -901,9 +939,9 @@ static inline void unblock_short_extra_support (struct sedf_dom_info* inf, #ifdef SEDF_STATS inf->pen_extra_blocks++; #endif - if (extraq_on(inf->owner, EXTRA_PEN_Q)) + if (extraq_on(inf->exec_domain, EXTRA_PEN_Q)) /*remove domain for possible resorting!*/ - extraq_del(inf->owner, EXTRA_PEN_Q); + extraq_del(inf->exec_domain, EXTRA_PEN_Q); else /*remember that we want to be on the penalty q so that we can continue when we (un-)block @@ -911,39 +949,39 @@ static inline void unblock_short_extra_support (struct sedf_dom_info* inf, inf->extra |= EXTRA_WANT_PEN_Q; /*(re-)add domain to the penalty extraq*/ - extraq_add_sort_update(inf->owner, + extraq_add_sort_update(inf->exec_domain, EXTRA_PEN_Q, 0); } } /*give it a fresh slice in the next period!*/ inf->cputime = 0; } -static inline void unblock_long_vcons(struct sedf_dom_info* inf, s_time_t now) +static inline void unblock_long_vcons(struct sedf_edom_info* inf, s_time_t now) { /* align to next future period */ - inf->absdead += ((now - inf->absdead) / inf->period + 1) + inf->deadl_abs += (DIV_UP(now - inf->deadl_abs, inf->period) +1) * inf->period; inf->cputime = 0; } -static inline void unblock_long_cons_a (struct sedf_dom_info* inf, +static inline void unblock_long_cons_a (struct sedf_edom_info* inf, s_time_t now) { /*treat the time the domain was blocked in the CURRENT period as consumed by the domain*/ - inf->cputime = (now - inf->absdead) % inf->period; + inf->cputime = (now - inf->deadl_abs) % inf->period; if (inf->cputime + EXTRA_QUANTUM > inf->slice) { /*we don't have a reasonable amount of time in our slice left :( => start in next period!*/ unblock_long_vcons(inf, now); } } -static inline void unblock_long_cons_b(struct sedf_dom_info* inf,s_time_t now) { +static inline void unblock_long_cons_b(struct sedf_edom_info* inf,s_time_t now) { /*Conservative 2b*/ /*Treat the unblocking time as a start of a new period */ - inf->absdead = now + inf->period; + inf->deadl_abs = now + inf->period; inf->cputime = 0; } -static inline void unblock_long_cons_c(struct sedf_dom_info* inf,s_time_t now) { +static inline void unblock_long_cons_c(struct sedf_edom_info* inf,s_time_t now) { if (likely(inf->latency)) { /*scale the slice and period accordingly to the latency hint*/ /*reduce period temporarily to the latency hint*/ @@ -954,7 +992,7 @@ static inline void unblock_long_cons_c(struct sedf_dom_info* inf,s_time_t now) { /*scale slice accordingly, so that utilisation stays the same*/ inf->slice = (inf->period * inf->slice_orig) / inf->period_orig; - inf->absdead = now + inf->period; + inf->deadl_abs = now + inf->period; inf->cputime = 0; } else { @@ -963,10 +1001,10 @@ static inline void unblock_long_cons_c(struct sedf_dom_info* inf,s_time_t now) { } } /*a new idea of dealing with short blocks: burst period scaling*/ -static inline void unblock_short_burst(struct sedf_dom_info* inf, s_time_t now) +static inline void unblock_short_burst(struct sedf_edom_info* inf, s_time_t now) { /*treat blocked time as consumed by the domain*/ - inf->cputime += now - inf->absblock; + inf->cputime += now - inf->block_abs; if (inf->cputime + EXTRA_QUANTUM <= inf->slice) { /*if we can still use some time in the current slice @@ -979,11 +1017,11 @@ static inline void unblock_short_burst(struct sedf_dom_info* inf, s_time_t now) else { /*we don't have a reasonable amount of time in our slice left => switch to burst mode*/ - if (likely(inf->absunblock)) { + if (likely(inf->unblock_abs)) { /*set the period-length to the current blocking interval, possible enhancements: average over last blocking intervals, user-specified minimum,...*/ - inf->period = now - inf->absunblock; + inf->period = now - inf->unblock_abs; /*check for overflow on multiplication*/ ASSERT((inf->period < ULONG_MAX) && (inf->slice_orig < ULONG_MAX)); @@ -992,18 +1030,18 @@ static inline void unblock_short_burst(struct sedf_dom_info* inf, s_time_t now) inf->slice = (inf->period * inf->slice_orig) / inf->period_orig; /*set new (shorter) deadline*/ - inf->absdead += inf->period; + inf->deadl_abs += inf->period; } else { /*in case we haven't unblocked before start in next period!*/ inf->cputime=0; - inf->absdead += inf->period; + inf->deadl_abs += inf->period; } } - inf->absunblock = now; + inf->unblock_abs = now; } -static inline void unblock_long_burst(struct sedf_dom_info* inf,s_time_t now) { +static inline void unblock_long_burst(struct sedf_edom_info* inf, s_time_t now) { if (unlikely(inf->latency && (inf->period > inf->latency))) { /*scale the slice and period accordingly to the latency hint*/ inf->period = inf->latency; @@ -1013,7 +1051,7 @@ static inline void unblock_long_burst(struct sedf_dom_info* inf,s_time_t now) { /*scale slice accordingly, so that utilisation stays the same*/ inf->slice = (inf->period * inf->slice_orig) / inf->period_orig; - inf->absdead = now + inf->period; + inf->deadl_abs = now + inf->period; inf->cputime = 0; } else { @@ -1023,16 +1061,16 @@ static inline void unblock_long_burst(struct sedf_dom_info* inf,s_time_t now) { when we are in sync with the device!*/ unblock_long_cons_b(inf, now); } - inf->absunblock = now; + inf->unblock_abs = now; } #define DOMAIN_EDF 1 #define DOMAIN_EXTRA_PEN 2 #define DOMAIN_EXTRA_UTIL 3 #define DOMAIN_IDLE 4 -static inline int get_run_type(struct domain* d) { - struct sedf_dom_info* inf = DOM_INFO(d); - if (is_idle_task(d)) +static inline int get_run_type(struct exec_domain* d) { + struct sedf_edom_info* inf = EDOM_INFO(d); + if (is_idle_task(d->domain)) return DOMAIN_IDLE; if (inf->extra & EXTRA_RUN_PEN) return DOMAIN_EXTRA_PEN; @@ -1049,11 +1087,11 @@ static inline int get_run_type(struct domain* d) { In the same class priorities are assigned as following: EDF: early deadline > late deadline L0 extra-time: lower score > higher score*/ -static inline int should_switch(struct domain* cur, struct domain* other, - s_time_t now) { - struct sedf_dom_info *cur_inf, *other_inf; - cur_inf = DOM_INFO(cur); - other_inf = DOM_INFO(other); +static inline int should_switch(struct exec_domain* cur, + struct exec_domain* other, s_time_t now) { + struct sedf_edom_info *cur_inf, *other_inf; + cur_inf = EDOM_INFO(cur); + other_inf = EDOM_INFO(other); /*check whether we need to make an earlier sched-decision*/ if ((PERIOD_BEGIN(other_inf) < @@ -1082,32 +1120,35 @@ static inline int should_switch(struct domain* cur, struct domain* other, return 1; } } -void sedf_wake(struct domain *d) { +void sedf_wake(struct exec_domain *d) { s_time_t now = NOW(); - struct sedf_dom_info* inf = DOM_INFO(d); + struct sedf_edom_info* inf = EDOM_INFO(d); - PRINT(3,"sedf_wake was called, domain-id %i\n",d->id); + PRINT(3,"sedf_wake was called, domain-id %i.%i\n",d->domain->id, d->eid); - if (unlikely(is_idle_task(d))) + if (unlikely(is_idle_task(d->domain))) return; if ( unlikely(__task_on_queue(d)) ) { - PRINT(3,"\tdomain %i is already in some queue\n",d->id); + PRINT(3,"\tdomain %i.%i is already in some queue\n", + d->domain->id, d->eid); return; } if ( unlikely(extraq_on(d,EXTRA_UTIL_Q) || extraq_on(d,EXTRA_PEN_Q)) ) { - PRINT(3,"\tdomain %i is already in the extraQ\n",d->id); + PRINT(3,"\tdomain %i.%i is already in the extraQ\n", + d->domain->id, d->eid); } - if (unlikely(inf->absdead == 0)) + if (unlikely(inf->deadl_abs == 0)) /*initial setup of the deadline*/ - inf->absdead = now + inf->slice; + inf->deadl_abs = now + inf->slice; - PRINT(3,"waking up domain %i (deadl= %llu period= %llu "\ - "now= %llu)\n",d->id,inf->absdead,inf->period,now); + PRINT(3,"waking up domain %i.%i (deadl= %llu period= %llu "\ + "now= %llu)\n", d->domain->id, d->eid, inf->deadl_abs, + inf->period, now); #ifdef SEDF_STATS inf->block_tot++; #endif - if (unlikely(now< PERIOD_BEGIN(inf))) { + if (unlikely(now < PERIOD_BEGIN(inf))) { PRINT(4,"extratime unblock\n"); /*this might happen, imagine unblocking in extra-time!*/ #if (EXTRA == EXTRA_BLOCK_WEIGHT) @@ -1134,7 +1175,7 @@ void sedf_wake(struct domain *d) { /*This is very very unlikely, ie. might even be an error?!*/ } else { - if (now < inf->absdead) { + if (now < inf->deadl_abs) { PRINT(4,"short unblocking\n"); /*short blocking*/ #ifdef SEDF_STATS @@ -1194,24 +1235,25 @@ void sedf_wake(struct domain *d) { } } - PRINT(3,"woke up domain %i (deadl= %llu period= %llu "\ - "now= %llu)\n",d->id,inf->absdead,inf->period,now); + PRINT(3,"woke up domain %i.%i (deadl= %llu period= %llu "\ + "now= %llu)\n", d->domain->id, d->eid, inf->deadl_abs, + inf->period, now); __add_to_waitqueue_sort(d); PRINT(3,"added to waitq\n"); #ifdef SEDF_STATS /*do some statistics here...*/ - if (inf->absblock != 0) { - inf->block_time_tot += now - inf->absblock; + if (inf->block_abs != 0) { + inf->block_time_tot += now - inf->block_abs; inf->penalty_time_tot += - PERIOD_BEGIN(inf) + inf->cputime - inf->absblock; + PERIOD_BEGIN(inf) + inf->cputime - inf->block_abs; } #endif /*sanity check: make sure each extra-aware domain IS on the util-q!*/ /*if (inf->extra & EXTRA_AWARE) { if (!extraq_on(d, EXTRA_UTIL_Q)) - printf("sedf_wake: domain %i is extra-aware, "\ - "but NOT on L1 extraq!\n",d->id); + printf("sedf_wake: domain %i.%i is extra-aware, "\ + "but NOT on L1 extraq!\n",d->domain->id, d->eid); }*/ /*check whether the awakened task needs to invoke the do_schedule @@ -1226,34 +1268,34 @@ void sedf_wake(struct domain *d) { } /*Print a lot of use-{full, less} information about a domains in the system*/ -static void sedf_dump_domain(struct domain *d) { - printk("%u has=%c ", d->id, - test_bit(DF_RUNNING, &d->flags) ? 'T':'F'); +static void sedf_dump_domain(struct exec_domain *d) { + printk("%i.%i has=%c ", d->domain->id, d->eid, + test_bit(EDF_RUNNING, &d->ed_flags) ? 'T':'F'); printk("p=%llu sl=%llu ddl=%llu w=%hu c=%llu sc=%i xtr(%s)=%llu", - DOM_INFO(d)->period, DOM_INFO(d)->slice, DOM_INFO(d)->absdead, - DOM_INFO(d)->weight, d->cpu_time, DOM_INFO(d)->score[EXTRA_UTIL_Q], - (DOM_INFO(d)->extra & EXTRA_AWARE) ? "yes" : "no", - DOM_INFO(d)->extra_time_tot); + EDOM_INFO(d)->period, EDOM_INFO(d)->slice, EDOM_INFO(d)->deadl_abs, + EDOM_INFO(d)->weight, d->cpu_time, EDOM_INFO(d)->score[EXTRA_UTIL_Q], + (EDOM_INFO(d)->extra & EXTRA_AWARE) ? "yes" : "no", + EDOM_INFO(d)->extra_time_tot); if (d->cpu_time !=0) - printf(" (%lu%)", (DOM_INFO(d)->extra_time_tot * 100) + printf(" (%lu%)", (EDOM_INFO(d)->extra_time_tot * 100) / d->cpu_time); #ifdef SEDF_STATS - if (DOM_INFO(d)->block_time_tot!=0) - printf(" pen=%lu%", (DOM_INFO(d)->penalty_time_tot * 100) / - DOM_INFO(d)->block_time_tot); - if (DOM_INFO(d)->block_tot!=0) + if (EDOM_INFO(d)->block_time_tot!=0) + printf(" pen=%lu%", (EDOM_INFO(d)->penalty_time_tot * 100) / + EDOM_INFO(d)->block_time_tot); + if (EDOM_INFO(d)->block_tot!=0) printf("\n blks=%lu sh=%lu (%lu%) (shc=%lu (%lu%) shex=%i "\ "shexsl=%i) l=%lu (%lu%) avg: b=%llu p=%llu", - DOM_INFO(d)->block_tot, DOM_INFO(d)->short_block_tot, - (DOM_INFO(d)->short_block_tot * 100) - / DOM_INFO(d)->block_tot, DOM_INFO(d)->short_cont, - (DOM_INFO(d)->short_cont * 100) / DOM_INFO(d)->block_tot, - DOM_INFO(d)->pen_extra_blocks, - DOM_INFO(d)->pen_extra_slices, - DOM_INFO(d)->long_block_tot, - (DOM_INFO(d)->long_block_tot * 100) / DOM_INFO(d)->block_tot, - (DOM_INFO(d)->block_time_tot) / DOM_INFO(d)->block_tot, - (DOM_INFO(d)->penalty_time_tot) / DOM_INFO(d)->block_tot); + EDOM_INFO(d)->block_tot, EDOM_INFO(d)->short_block_tot, + (EDOM_INFO(d)->short_block_tot * 100) + / EDOM_INFO(d)->block_tot, EDOM_INFO(d)->short_cont, + (EDOM_INFO(d)->short_cont * 100) / EDOM_INFO(d)->block_tot, + EDOM_INFO(d)->pen_extra_blocks, + EDOM_INFO(d)->pen_extra_slices, + EDOM_INFO(d)->long_block_tot, + (EDOM_INFO(d)->long_block_tot * 100) / EDOM_INFO(d)->block_tot, + (EDOM_INFO(d)->block_time_tot) / EDOM_INFO(d)->block_tot, + (EDOM_INFO(d)->penalty_time_tot) / EDOM_INFO(d)->block_tot); #endif printf("\n"); } @@ -1261,10 +1303,11 @@ static void sedf_dump_domain(struct domain *d) { /*dumps all domains on hte specified cpu*/ static void sedf_dump_cpu_state(int i) { - struct list_head *list, *queue, *tmp; + struct list_head *list, *queue, *tmp; + struct sedf_edom_info *d_inf; + struct domain *d; + struct exec_domain *ed; int loop = 0; - struct sedf_dom_info *d_inf; - struct domain* d; printk("now=%llu\n",NOW()); queue = RUNQ(i); @@ -1272,8 +1315,8 @@ static void sedf_dump_cpu_state(int i) (unsigned long) queue->next, (unsigned long) queue->prev); list_for_each_safe ( list, tmp, queue ) { printk("%3d: ",loop++); - d_inf = list_entry(list, struct sedf_dom_info, list); - sedf_dump_domain(d_inf->owner); + d_inf = list_entry(list, struct sedf_edom_info, list); + sedf_dump_domain(d_inf->exec_domain); } queue = WAITQ(i); loop = 0; @@ -1281,8 +1324,8 @@ static void sedf_dump_cpu_state(int i) (unsigned long) queue->next, (unsigned long) queue->prev); list_for_each_safe ( list, tmp, queue ) { printk("%3d: ",loop++); - d_inf = list_entry(list, struct sedf_dom_info, list); - sedf_dump_domain(d_inf->owner); + d_inf = list_entry(list, struct sedf_edom_info, list); + sedf_dump_domain(d_inf->exec_domain); } queue = EXTRAQ(i,EXTRA_PEN_Q); loop = 0; @@ -1290,10 +1333,10 @@ static void sedf_dump_cpu_state(int i) (unsigned long)queue, (unsigned long) queue->next, (unsigned long) queue->prev); list_for_each_safe ( list, tmp, queue ) { - d_inf = list_entry(list, struct sedf_dom_info, + d_inf = list_entry(list, struct sedf_edom_info, extralist[EXTRA_PEN_Q]); printk("%3d: ",loop++); - sedf_dump_domain(d_inf->owner); + sedf_dump_domain(d_inf->exec_domain); } queue = EXTRAQ(i,EXTRA_UTIL_Q); loop = 0; @@ -1301,36 +1344,40 @@ static void sedf_dump_cpu_state(int i) (unsigned long)queue, (unsigned long) queue->next, (unsigned long) queue->prev); list_for_each_safe ( list, tmp, queue ) { - d_inf = list_entry(list, struct sedf_dom_info, + d_inf = list_entry(list, struct sedf_edom_info, extralist[EXTRA_UTIL_Q]); printk("%3d: ",loop++); - sedf_dump_domain(d_inf->owner); + sedf_dump_domain(d_inf->exec_domain); } loop = 0; printk("\nnot on Q\n"); - for_each_domain(d) { - if (!__task_on_queue(d) && (d->processor == i)) { - printk("%3d: ",loop++); - sedf_dump_domain(d); + for_each_domain(d) + for_each_exec_domain(d, ed) + { + if (!__task_on_queue(ed) && (ed->processor == i)) { + printk("%3d: ",loop++); + sedf_dump_domain(ed); + } } - } } /*Adjusts periods and slices of the domains accordingly to their weights*/ -static inline int sedf_adjust_weights(struct domain *p, -struct sched_adjdom_cmd *cmd) { - int sumw[NR_CPUS]; - s_time_t sumt[NR_CPUS]; - int cpu; +static inline int sedf_adjust_weights(struct sched_adjdom_cmd *cmd) { + struct exec_domain *p; + struct domain *d; + int sumw[NR_CPUS]; + s_time_t sumt[NR_CPUS]; + int cpu; for (cpu=0; cpu < NR_CPUS; cpu++) { sumw[cpu] = 0; sumt[cpu] = 0; } /*sum up all weights*/ - for_each_domain(p) { - if (DOM_INFO(p)->weight) - sumw[p->processor] += DOM_INFO(p)->weight; + for_each_domain(d) + for_each_exec_domain(d, p) { + if (EDOM_INFO(p)->weight) + sumw[p->processor] += EDOM_INFO(p)->weight; else { /*don't modify domains who don't have a weight, but sum up the time they need, projected to a WEIGHT_PERIOD, @@ -1338,18 +1385,19 @@ struct sched_adjdom_cmd *cmd) { domains*/ /*check for overflows*/ ASSERT((WEIGHT_PERIOD < ULONG_MAX) - && (DOM_INFO(p)->slice_orig < ULONG_MAX)); + && (EDOM_INFO(p)->slice_orig < ULONG_MAX)); sumt[p->processor] += (WEIGHT_PERIOD * - DOM_INFO(p)->slice_orig) / DOM_INFO(p)->period_orig; + EDOM_INFO(p)->slice_orig) / EDOM_INFO(p)->period_orig; } } /*adjust all slices (and periods) to the new weight*/ - for_each_domain(p) { - if (DOM_INFO(p)->weight) { - DOM_INFO(p)->period_orig = - DOM_INFO(p)->period = WEIGHT_PERIOD; - DOM_INFO(p)->slice_orig = - DOM_INFO(p)->slice = (DOM_INFO(p)->weight * + for_each_domain(d) + for_each_exec_domain(d, p) { + if (EDOM_INFO(p)->weight) { + EDOM_INFO(p)->period_orig = + EDOM_INFO(p)->period = WEIGHT_PERIOD; + EDOM_INFO(p)->slice_orig = + EDOM_INFO(p)->slice = (EDOM_INFO(p)->weight * (WEIGHT_PERIOD -WEIGHT_SAFETY - sumt[p->processor])) / sumw[p->processor]; } @@ -1359,6 +1407,8 @@ struct sched_adjdom_cmd *cmd) { /* set or fetch domain scheduling parameters */ static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { + struct exec_domain *ed; + PRINT(2,"sedf_adjdom was called, domain-id %i new period %llu "\ "new slice %llu\nlatency %llu extra:%s\n", p->id, cmd->u.sedf.period, cmd->u.sedf.slice, @@ -1370,33 +1420,40 @@ static int sedf_adjdom(struct domain *p, struct sched_adjdom_cmd *cmd) { return -EINVAL; /*weight driven domains*/ if (cmd->u.sedf.weight) { - DOM_INFO(p)->weight = cmd->u.sedf.weight; + for_each_exec_domain(p, ed) + EDOM_INFO(ed)->weight = cmd->u.sedf.weight; } else { /*time driven domains*/ - DOM_INFO(p)->weight = 0; - /* sanity checking! */ - if(cmd->u.sedf.slice > cmd->u.sedf.period ) - return -EINVAL; - DOM_INFO(p)->period_orig = - DOM_INFO(p)->period = cmd->u.sedf.period; - DOM_INFO(p)->slice_orig = - DOM_INFO(p)->slice = cmd->u.sedf.slice; + for_each_exec_domain(p, ed) { + /* sanity checking! */ + if(cmd->u.sedf.slice > cmd->u.sedf.period ) + return -EINVAL; + EDOM_INFO(ed)->weight = 0; + EDOM_INFO(ed)->period_orig = + EDOM_INFO(ed)->period = cmd->u.sedf.period; + EDOM_INFO(ed)->slice_orig = + EDOM_INFO(ed)->slice = cmd->u.sedf.slice; + } } - if (sedf_adjust_weights(p,cmd)) + if (sedf_adjust_weights(cmd)) return -EINVAL; - DOM_INFO(p)->extra = (DOM_INFO(p)-> extra & ~EXTRA_AWARE) - | (cmd->u.sedf.extratime & EXTRA_AWARE); - DOM_INFO(p)->latency = cmd->u.sedf.latency; - extraq_check(p); + + for_each_exec_domain(p, ed) { + EDOM_INFO(ed)->extra = (EDOM_INFO(ed)->extra & + ~EXTRA_AWARE) | (cmd->u.sedf.extratime & EXTRA_AWARE); + EDOM_INFO(ed)->latency = cmd->u.sedf.latency; + extraq_check(ed); + } } else if ( cmd->direction == SCHED_INFO_GET ) { - cmd->u.sedf.period = DOM_INFO(p)->period; - cmd->u.sedf.slice = DOM_INFO(p)->slice; - cmd->u.sedf.extratime = DOM_INFO(p)->extra & EXTRA_AWARE; - cmd->u.sedf.latency = DOM_INFO(p)->latency; - cmd->u.sedf.weight = DOM_INFO(p)->weight; + cmd->u.sedf.period = EDOM_INFO(p->exec_domain[0])->period; + cmd->u.sedf.slice = EDOM_INFO(p->exec_domain[0])->slice; + cmd->u.sedf.extratime = EDOM_INFO(p->exec_domain[0])->extra + & EXTRA_AWARE; + cmd->u.sedf.latency = EDOM_INFO(p->exec_domain[0])->latency; + cmd->u.sedf.weight = EDOM_INFO(p->exec_domain[0])->weight; } PRINT(2,"sedf_adjdom_finished\n"); return 0; -- 2.30.2